<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" >
<head>
<title>Feed preview</title>
<style type="text/css">

html,
body
{
    margin:0;
    padding:0;
    border:0;
}
body
{
    color:#000;
    background:#fff;
    text-align:center;
    font:normal normal .9em/1.5em sans-serif;
    padding:2em 0;
}
body[class]:after
{
    position:fixed;
    top:0;
    left:0;
    right:0;
    bottom:0;
    background:#fff;
    content:attr(class);
    text-transform:uppercase;
    padding-top:30%;
    text-align:center;
}
h1
{
    margin:0;
    font-size:1.5em;
    line-height:1.5em;
    display:inline;
}
h1:before
{
    display:inline;
    overflow:hidden;
    vertical-align:middle;
    content:-o-skin('Mail Newsfeeds');
    margin-right:.2em;
    line-height:1.5em;
}

#heading
{
    background:#a00 url(data:image/png,%89PNG%0D%0A%1A%0A%00%00%00%0DIHDR%00%00%00%04%00%00%00%C0%08%06%00%00%00%23%88%C2%DC%00%00%00%04gAMA%00%00%AF%C87%05%8A%E9%00%00%00%19tEXtSoftware%00Adobe%20ImageReadyq%C9e%3C%00%00%00%3AIDATx%DA%EC%D0%21%0E%000%08%04Ah%8A%EF%FF%3F%7BE%12%0C%02%BB%9B%9C%19y.%C9j%C7Z%00%00%00%000%82%E7%A2%C2%CD%BD%0E%C1c%00%00%00%C0%0E%BE%00%03%00k%9B%04%9A%B9%BDH%AF%00%00%00%00IEND%AEB%60%82) repeat-x center center;
    color:#fff;
    padding:8px;
    margin:1em 0;
    border:2px solid #eee;
    border-width:2px 0;
}
#heading > *
{
    display:inline-block;
    width:50ex;
    line-height:2em;
}
#heading a
{
    color:#fff;
}
#heading button
{
    margin:0 10ex;
    width:30ex;
}

a
{
    text-decoration:none;
}

a:hover
{
    text-decoration:underline;
}
#items
{
    display:block;
    clear:both;
    text-align:center;
    margin:2em 0;
    padding:0;
    overflow:hidden;
}

#items > ul
{
    position:relative;
    list-style:none;
    margin:0;
    padding:0;
    border:0;
    width:auto;
    display:inline-block;
    text-align:left;
}
#items > ul > li:last-child
{
    display:none;
}
#items > ul > li
{
    vertical-align:top;
    font:normal normal .8em/1.6em sans-serif;
    display:inline-block;
    margin:2em;
    padding:0;
    width:50ex;
}
#items > ul > li > h2
{
    font:normal lighter 1.66em/1.2em sans-serif;
    margin:0;
    color:#000;
    overflow:hidden;
    -o-text-overflow:ellipsis;
}
#items > ul > li > h2 > a
{
    display:block;
    color:inherit;
    padding:0;
}
#items > ul > li a
{
    color:#b00;
}
#items > ul > li > div
{
    border-top:1px solid #ccc;
    text-align:justify;
    margin:1em 0 0 0;
    padding:1em 0 3em 0;
    color:#555;
    vertical-align:top;
    -o-text-overflow:ellipsis;
}
#items > ul > li > div pre
{
    font:.9em/.9em monospace;
    background:#eee;
    overflow:auto;
    border:1px solid #999;
    border-width:1px 0;
    padding:1em;
}
#items > ul > li > div pre a
{
    font-style:normal;
}

#items > ul > li > div p
{
    margin:0 0 2em 0;
}
#items > ul > li > div a
{
    font-style:italic;
    margin-right:.25em;
}
#items > ul > li > div img
{
    display:none;
}
#items > ul > li > div img[src]
{
    float:left;
    display:inline-block;
    border:1px solid #aaa;
    padding:1px;
    margin:1px;
    margin:1px 8px 8px 1px;
    max-width:100%;
}
#items > ul > li > div a img[src]
{
    border-color:#a00;
}
#items > ul > li > div a:hover img
{
    border-width:2px;
    margin:0px 7px 7px 0px;
}
#footer
{
    font-size:.85em;
}
#footer a
{
    color:#b00;
}

/*
 *  extra rules for HANDHELD devices
 */
@media handheld
{
    body
    {
        font:normal normal 1em/1.5em sans-serif;
        padding:1em 0;
    }
    #heading > *,
    #heading > button
    {
        display:inline;
        width:auto;
        margin:0 .5em;
        line-height:auto;
        height:auto;
    }
    #items
    {
        margin:1em 0;
    }
    #items > ul
    {
        display:block;
    }
    #items > ul > li
    {
        font:normal normal 1em/1.5em sans-serif;
        display:block;
        padding:1em;
        margin:0;
        width:auto;
        background:#fff;
    }
    #items > ul > li:nth-child(2n)
    {
        background:#eee;
    }
    #items > ul > li > h2
    {
        font:normal bold 1.33em/1.2em sans-serif;
    }
    #items > ul > li > div
    {
        border:0;
        padding:0;
        margin:0;
    }
    #items > ul > li > div:after
    {
        clear:both;
        content:' ';
        display:block;
    }
    #items > ul > li > div pre
    {
        font:1em/1em monospace;
        background:#ddd;
    }
    #items > ul > li > div a
    {
        font-style:normal;
    }
    #footer a
    {
        font-size:1em;
    }
}


</style>
<script type="text/javascript">
// <![CDATA[

String.prototype.trim = function()
{
	return this.replace( /^\s+|\s+$/g, '' );
}

/*
 *	whiteList
 *	tags + attributes and method to validate them
 */
HTMLElement.prototype.whiteList =
{
	'A':
	{
	    '__precondition__':function( node )
	    {
			return node.hasAttribute('href') && node.whiteList['A'].href.call( {value:node.getAttribute('href')}, node );
	    },
		'href':function( node )
		{
			return null!=this.value.match( /^https?:\/\//i );
		},
		'title':true
	}
	,'IMG':
	{
	    '__precondition__':function( node )
	    {
			node.setAttribute( 'title', node.getAttribute('title')||node.getAttribute('src') )
			return node.hasAttribute('src') && node.whiteList['IMG'].src.call( {value:node.getAttribute('src')}, node );
	    },
		'src':function( node )
		{
			return null!=this.value.match( /^https?:\/\//i );
		},
		'alt':true,
		'title':true
	}
	,'P':{}
	,'PRE':{}
	,'UL':{}
	,'OL':{}
	,'LI':{}
	,'DL':{}
	,'DT':{}
	,'H1':{}
	,'H2':{}
	,'H3':{}
	,'H4':{}
	,'H5':{}
	,'H6':{}
	,'BR':{}
}
/**
 *	Prototype extension to simplify adding and sanitizing markup to an element.
 *	arguments = some strings containing the HTML markup to sanitize and append
 */
HTMLElement.prototype.appendMarkup = function( content, maxLength )
{
	var    maxLength   = maxLength||Infinity,
	       dummy       = document.createElement('div');
	dummy.innerHTML    = content;

    //  sanitize using the whiteList
	dummy.sanitize();

	//	append DOM tree of dummy in this
	var i = 0, node;
	while( maxLength>this.textContent.length && dummy.firstChild )
	{
		this.appendChild( dummy.firstChild );
        i++;
    }

    //maxLength = Infinity;
    if( dummy.firstChild && maxLength!=Infinity )
    {
        this.cutOff( maxLength );
    }


    return this;
}
/**
 *	Prototype extension to sanitize the attributes and HTMLElements
 *	whiteList = { 'NODENAME_0':{'attribute_0':function(){},'attribute_1':function(){}} }
 */
HTMLElement.prototype.sanitize = function()
{
	// recurse
	var i=0, previousNodeName='/', currentNode;
	while( currentNode=this.childNodes[i] )
	{
		var nodeName	= currentNode.nodeName;

		if
        (
            currentNode.nodeType==1
            &&
            (
                    !this.whiteList[nodeName]
                ||  ( this.whiteList[nodeName] && this.whiteList[nodeName].__precondition__ && !this.whiteList[nodeName].__precondition__(currentNode) )
                ||  ( nodeName=='BR' && ( previousNodeName=='BR' || previousNodeName=='P' ) )
            )
        )
		{
    		// either it's not in the whiteList or does not meet the preconditions or is an extra BR -> replace currentNode by its content
    		while( currentNode.firstChild )
    		{
    			this.insertBefore( currentNode.firstChild.cloneNode( true ), currentNode );
    			currentNode.removeChild( currentNode.firstChild );
    		}
            this.removeChild( currentNode );
		}
		else
	    {
	        if( currentNode.nodeType==1 )
	        {
    			//  in the whiteList and meet the preconditions
    			//	-> sanitize the attributes
    			for( var j=currentNode.attributes.length,attribute; attribute=currentNode.attributes[--j]; )
    		    {
                    var attrSanity = this.whiteList[nodeName][attribute.name];
    				if( attrSanity===undefined || ( attrSanity!==true && false==attrSanity.apply(attribute,[currentNode] ) ) )
    				{
						currentNode.removeAttribute( attribute.name );
    				}
                }

                //  -> and recurse
    			currentNode.sanitize();
    	        previousNodeName = nodeName;
	        }
	        //  => next!
	        i++;
	    }
	}
}
/*
 *	Prototype extension to cutOff a DOM tree so as to get a textContent <= maxLength
 */
Element.prototype.cutOff = function( maxLength, base )
{
    var base = base||this;
    while( this.lastChild )
    {
        if( this.lastChild.nodeType==3 && this.lastChild.nodeValue.length>base.textContent.length-maxLength )
        {
            this.lastChild.nodeValue = this.lastChild.nodeValue.slice( 0, this.lastChild.nodeValue.length-base.textContent.length+maxLength ) +'...';
            return true;
        }
        if( this.lastChild.nodeType==1 && this.lastChild.cutOff( maxLength, base ) )
        {
            return true;
        }
        this.removeChild( this.lastChild );
    }
    return false;
}


//  failsafe for opera.locale.getLocaleString
opera.locale=opera.locale||{'getLocaleString':function(){return ''}};

/*
 *  outputFeed
 */
function outputFeed( feed, status )
{
    if( !feed )
    {
        var statusName = ['NO FEED ITEMS','CANCELED','REFRESH POSTPONED','NOT MODIFIED','OUT OF MEMORY','SERVER TIMEOUT','LOADING ERROR','PARSING ERROR']
        document.body.className = 'error #'+ status +' ( '+ statusName[ status ] +' )';
        return false;
    }

    //  l10n the 'footer' note including a link
    var footer      = document.getElementById('footer'),
        splitText   = (opera.locale.getLocaleString( 'S_WEBFEEDS_FOOTER' )||'This page was generated by Opera from %s').split('%s');

    footer.firstChild.nodeValue = splitText.shift()||'';
    footer.lastChild.nodeValue = splitText.join(' ')||'';


    //  l10n the 'learn' link
    (document.getElementById('learn')||{firstChild:{}}).firstChild.nodeValue = opera.locale.getLocaleString( 'S_WEBFEEDS_SUBSCRIBE_HINT' )||'Learn more about feeds';

    //  subscribeNative?
    var button = document.getElementById('subscribe');
    if( button )
    {
        if( 'function'==typeof(opera.feeds.subscribeNative) )
        {
            button.addEventListener( 'click', function(){ opera.feeds.subscribeNative(location.href); }, false );
            //  l10n the 'subscribe' button
            button.firstChild.nodeValue = opera.locale.getLocaleString( 'S_MINI_FEED_SUBSCRIBE' )||'Subscribe';
        }
        else
        {
            button.parentNode.removeChild( button );
        }
    }

    //    set title
    top.document.title = document.getElementById('feedTitle').firstChild.nodeValue = document.createElement( 'div' ).appendMarkup( feed.title.data ).textContent.trim()||feed.uri;
    document.body.removeAttribute( 'class' );

    //  walk the feed items
    var cutOff      = 768,
        hItemsUl    = document.getElementById('itemsUl'),
        noTilteStr  = opera.locale.getLocaleString( 'M_BREW_NO_TITLE' )||'<No Title>';
    for( var i=0,feedEntry; feedEntry=feed.entries[i++]; )
    {
        var itemLi = hItemsUl.lastChild.cloneNode( true );

        //  set the href
        itemLi.firstChild.firstChild.setAttribute( 'href', feedEntry.uri||'#' );

        //  set the title
        itemLi.firstChild.firstChild.firstChild.nodeValue = document.createElement( 'div' ).appendMarkup( feedEntry.title.data ).textContent.trim()||noTilteStr;

        //  write content
        if( feedEntry.content.isMarkup )
        {
            itemLi.lastChild.appendMarkup( (feedEntry.content.data.trim()||'\xa0'), cutOff );
        }
        else if( feedEntry.content.isPlainText )
        {
            itemLi.lastChild.appendChild( document.createTextNode( (feedEntry.content.data.trim()||'\xa0').slice( 0, cutOff ) ) );
        }
        else
        {
            itemLi.lastChild.appendChild( document.createTextNode( (feedEntry.content.data||'\xa0').slice( 0, cutOff ) ) );
        }

        //  append itemLi to hItemsUl
        hItemsUl.insertBefore( itemLi, hItemsUl.lastChild );
    }

    return true;
}

// ]]>
</script>
</head>
<body class='loading'>

    <h1 id="feedTitle">Title of the news feed</h1>
    <div id="heading"><span><a id="learn" href="opera:/help/feeds.html">Learn more about feeds</a></span><button id="subscribe">Subscribe</button></div>

    <div id="items">
        <ul id="itemsUl"><!-- template LI follows --><li><h2><a href="#">...</a></h2><div></div></li></ul>
    </div>



    <div id="footer">This page was generated by Opera from <a href="#">here</a>.</div>

<script type="text/javascript">
// <![CDATA[

window.addEventListener
(
    'load',
    function(/* window.load */)
    {
        var url     = location.href.split('#')[0],
            here    = document.getElementById('footer').getElementsByTagName('A')[0],
            theFeed = null;

        for( var i=0; theFeed=opera.feeds.allFeeds[i++]; )
        {
            if( url==theFeed.uri.split('#')[0] )
            {
                here.firstChild.nodeValue = here.href = theFeed.uri;
                break;
            }
        }
        outputFeed( theFeed );
    },
    false
);

//]]>
</script>
</body>
</html>